Remove proximity and temperature from garmin special data.
authoroliskoli <oliskoli>
Fri, 25 May 2007 10:13:21 +0000 (10:13 +0000)
committeroliskoli <oliskoli>
Fri, 25 May 2007 10:13:21 +0000 (10:13 +0000)
Extend wpt_flags with members for proximity and temperature.
Define macros for easy access to 'flagged' waypoint fields (as GMSD).

13 files changed:
compegps.c
defs.h
g7towin.c
garmin_fs.c
garmin_fs.h
garmin_txt.c
gdb.c
gpilots.c
kml.c
mapsource.c
ozi.c
stmsdf.c
unicsv.c

index b65b6912bc00480564dbc7fc9e725f16cf198d44..0aa41ef409180d67325220ec0262d0bd40ee0505 100644 (file)
@@ -205,8 +205,7 @@ parse_wpt_info(const char *buff, waypoint *wpt)             /* "w" */
                                case 7: break;                  /* ??? */
                                case 8:                         /* radius */
                                        fx = atof(c);
-                                       if (fx > 0)
-                                               wpt->proximity = fx;
+                                       if (fx > 0) WAYPT_SET(wpt, proximity, fx);
                                        break;
                        }
                }
@@ -450,7 +449,7 @@ write_waypt_cb(const waypoint *wpt)
                gbfprintf(fout, " %s", wpt->description);
        gbfprintf(fout, "\n");
        
-       if ((wpt->icon_descr != NULL) || (wpt->proximity > 0.0) || \
+       if ((wpt->icon_descr != NULL) || (wpt->wpt_flags.proximity) || \
            (option_icon != NULL))
        {
                char *icon = option_icon;
@@ -459,7 +458,7 @@ write_waypt_cb(const waypoint *wpt)
                        
                gbfprintf(fout, "w  %s,0,0.0,16777215,255,1,7,,%.1f\n",
                        (icon != NULL) ? icon : "Waypoint",
-                       (wpt->proximity > 0.0f) ? wpt->proximity : 0.0);
+                       WAYPT_GET(wpt, proximity, 0));
        }
        xfree(name);
 }
diff --git a/defs.h b/defs.h
index c0c68e56d12cd9e8adc09a250a0b3d031ea67ed6..7c19a356d5e98151b6bf7c4105f1c8edc0057bb1 100644 (file)
--- a/defs.h
+++ b/defs.h
@@ -283,8 +283,13 @@ typedef struct {
        unsigned int icon_descr_is_dynamic:1; 
        unsigned int shortname_is_synthetic:1;
        unsigned int cet_converted:1;           /* strings are converted to UTF8; interesting only for input */
+       unsigned int temperature:1;             /* temperature field set */
+       unsigned int proximity:1;               /* proximity field set */
 } wp_flags;
 
+#define WAYPT_SET(wpt,member,val) { wpt->member = (val); wpt->wpt_flags.member = 1; }
+#define WAYPT_GET(wpt,member,def) (wpt->wpt_flags.member) ? (wpt->member) : (def)
+
 /*
  * This is a waypoint, as stored in the GPSR.   It tries to not 
  * cater to any specific model or protocol.  Anything that needs to
index 5c52a77519549b776c16786e00dd59fca8547688..a3e2517b139e1a960b1ac453117aced7df1c4bef 100644 (file)
--- a/g7towin.c
+++ b/g7towin.c
@@ -183,12 +183,12 @@ parse_line(char *buff, int index, const char *delimiter, waypoint *wpt)
                                /* !!! NO BREAK !!! */
                        case WPT_cD_OFS + 1:
                        case WPT_cB_OFS + 6:
-                               GMSD_SET(temperature, atof(cin));
+                               WAYPT_SET(wpt, temperature, atof(cin));
                                break;
 
                        case WAYPT__OFS + 6: /* proximity */
                        case WPT_cD_OFS + 2:
-                               GMSD_SET(proximity, atof(cin));
+                               WAYPT_SET(wpt, proximity, atof(cin));
                                break;
 
                        case WPT_cB_OFS + 5: 
index 47afd54c8ddfb1ff47e7b755b54ed8b9efefbef2..d9c9a5ece04e3c682b05b982850250af8d7b7d33 100644 (file)
@@ -103,8 +103,8 @@ garmin_fs_xml_fprint(gbfile *ofd, const waypoint *waypt)
        
        if ((gmsd->flags.category && gmsd->category) || 
             gmsd->flags.depth || 
-            gmsd->flags.proximity || 
-            gmsd->flags.temperature || 
+            waypt->wpt_flags.proximity || 
+            waypt->wpt_flags.temperature || 
             gmsd->flags.display)
        {
                int space = 1;
@@ -115,10 +115,10 @@ garmin_fs_xml_fprint(gbfile *ofd, const waypoint *waypt)
                        "xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" " \
                        "xsi:schemaLocation=\"http://www.garmin.com/xmlschemas/GpxExtensions/v2 " \
                        "http://www.garmin.com/xmlschemas/GpxExtensions/v2/GpxExtensionsv2.xsd\">\n", space++ * 2, "");
-               if (gmsd->flags.proximity)
-                       gbfprintf(ofd, "%*s<gpxx:Proximity>%.6f</gpxx:Proximity>\n", space * 2, "", gmsd->proximity);
-               if (gmsd->flags.temperature)
-                       gbfprintf(ofd, "%*s<gpxx:Temperature>%.6f</gpxx:Temperature>\n", space * 2, "", gmsd->temperature);
+               if (waypt->wpt_flags.proximity)
+                       gbfprintf(ofd, "%*s<gpxx:Proximity>%.6f</gpxx:Proximity>\n", space * 2, "", waypt->proximity);
+               if (waypt->wpt_flags.temperature)
+                       gbfprintf(ofd, "%*s<gpxx:Temperature>%.6f</gpxx:Temperature>\n", space * 2, "", waypt->temperature);
                if (gmsd->flags.depth)
                        gbfprintf(ofd, "%*s<gpxx:Depth>%.6f</gpxx:Depth>\n", space * 2, "", gmsd->depth);
                if (gmsd->flags.display)
@@ -180,10 +180,19 @@ garmin_fs_xml_convert(const int base_tag, int tag, const char *cdatastr, waypoin
        tt_garmin_category, -> 7
 */
        switch(tag) {
-       case 2: GMSD_SET(proximity, atof(cdatastr)); break;
-       case 3: GMSD_SET(temperature, atof(cdatastr)); break;
-       case 4: GMSD_SET(depth, atof(cdatastr)); break;
-       case 5: if (case_ignore_strcmp(cdatastr, "SymbolOnly") == 0) {
+       case 2:
+               waypt->proximity = atof(cdatastr); 
+               waypt->wpt_flags.proximity = (*cdatastr); 
+               break;
+       case 3:
+               waypt->temperature = atof(cdatastr);
+               waypt->wpt_flags.temperature = (*cdatastr);
+               break;
+       case 4:
+               GMSD_SET(depth, atof(cdatastr)); 
+               break;
+       case 5:
+               if (case_ignore_strcmp(cdatastr, "SymbolOnly") == 0) {
                        GMSD_SET(display, gt_display_mode_symbol);
                }
                else if (case_ignore_strcmp(cdatastr, "SymbolAndDescription") == 0) {
@@ -270,8 +279,8 @@ garmin_fs_garmin_after_read(const GPS_PWay way, waypoint *wpt, const int protoid
        /* flagged data fields */
        GMSD_SET(display, gt_switch_display_mode_value(way->dspl, gps_waypt_type, 1));
        if (way->category != 0) GMSD_SET(category, way->category);
-       if (way->dst < 1.0e25f) GMSD_SET(proximity, way->dst);
-       if (way->temperature_populated) GMSD_SET(temperature, way->temperature);
+       if (way->dst < 1.0e25f) WAYPT_SET(wpt, proximity, way->dst);
+       if (way->temperature_populated) WAYPT_SET(wpt, temperature, way->temperature);
        if (way->dpth < 1.0e25f) GMSD_SET(depth, way->dpth);
        GMSD_SETNSTR(cc, way->cc, sizeof(way->cc));
        GMSD_SETNSTR(state, way->state, sizeof(way->state));
@@ -295,8 +304,8 @@ garmin_fs_garmin_before_write(const waypoint *wpt, GPS_PWay way, const int proto
                GMSD_GET(display, way->dspl), gps_waypt_type, 0);
        way->category = GMSD_GET(category, way->category);
        way->dpth = GMSD_GET(depth, way->dpth);
-       way->dst = GMSD_GET(proximity, way->dpth);
-       way->temperature = GMSD_GET(temperature, way->temperature);
+       way->dst = WAYPT_GET(wpt, proximity, way->dpth);
+       way->temperature = WAYPT_GET(wpt, temperature, way->temperature);
        
        GMSD_GETNSTR(cc, way->cc, sizeof(way->cc));
        GMSD_GETNSTR(city, way->city, sizeof(way->city));
index 7fb36f47616c088f180f6506ee77958d70c7f25b..eda53d320b1697f4ebbf95686e3f0bcc6fbc6273 100644 (file)
@@ -69,8 +69,6 @@ typedef struct {
        unsigned int display:1; 
        unsigned int category:1; 
        unsigned int depth:1; 
-       unsigned int proximity:1; 
-       unsigned int temperature:1; 
        unsigned int city:1;
        unsigned int state:1;
        unsigned int facility:1;
@@ -94,8 +92,6 @@ typedef struct garmin_fs_s
        gbint32 display;
        gbint16 category;
        double depth;                   /* depth in meters */
-       double proximity;               /* proximity distance in meters */
-       double temperature;
        char *city;                     /* city name */
        char *facility;                 /* facility name */
        char *state;                    /* state */
index 3638510d3af2538618a51e190eb8f8c6e1b7b8fe..7f17f0b1949235bd97a501c067e9b8134c64253a 100644 (file)
@@ -581,12 +581,12 @@ write_waypt(const waypoint *wpt)
                print_distance(x, 1, 0);
        gbfprintf(fout, "\t");
 
-       x = GMSD_GET(proximity, unknown_alt);
+       x = WAYPT_GET(wpt, proximity, unknown_alt);
        if (x != unknown_alt)
                print_distance(x, 0, 0);
        gbfprintf(fout, "\t");
        
-       x = GMSD_GET(temperature, unknown_alt);
+       x = WAYPT_GET(wpt, temperature, unknown_alt);
        if (x != unknown_alt) {
                if (gtxt_flags.celsius)
                        gbfprintf(fout, "%.f C", x);
@@ -1130,8 +1130,8 @@ parse_waypoint(void)
                                break;
                        case  5: if (parse_distance(str, &d)) wpt->altitude = d; break;
                        case  6: if (parse_distance(str, &d)) GMSD_SET(depth, d); break;
-                       case  7: if (parse_distance(str, &d)) GMSD_SET(proximity, d); break;
-                       case  8: if (parse_temperature(str, &d)) GMSD_SET(temperature, d); break;
+                       case  7: if (parse_distance(str, &d)) WAYPT_SET(wpt, proximity, d); break;
+                       case  8: if (parse_temperature(str, &d)) WAYPT_SET(wpt, temperature, d); break;
                        case  9: if (parse_display(str, &i)) GMSD_SET(display, i); break;
                        case 10: break; /* skip color */
                        case 11: 
diff --git a/gdb.c b/gdb.c
index 464899f37d98e49ad813a2c46b83a9aa86b6bf33..96fe4bd49b0475b9682a6beed562346ce37f09e8 100644 (file)
--- a/gdb.c
+++ b/gdb.c
 
 /*******************************************************************************/
 
-/* static char gdb_release[] = "$Revision: 1.51 $"; */
-static char gdb_release_date[] = "$Date: 2007/05/04 08:41:41 $";
+/* static char gdb_release[] = "$Revision: 1.52 $"; */
+static char gdb_release_date[] = "$Date: 2007/05/25 10:13:21 $";
 
 static gbfile *fin, *fout;
 static int gdb_ver, gdb_category, gdb_via, gdb_roadbook;
@@ -499,7 +499,7 @@ read_waypoint(gt_waypt_classes_e *waypt_class_out)
 #endif
        if (FREAD_C == 1) {
                double proximity = gbfgetdbl(fin);
-               GMSD_SET(proximity, proximity);
+               WAYPT_SET(res, proximity, proximity);
 #if GDB_DEBUG
                DBG(GDB_DBG_WPTe, 1)
                        printf(MYNAME "-wpt \"%s\" (%d): Proximity = %.1f\n",
@@ -1154,7 +1154,7 @@ write_waypoint(
        FWRITE_LATLON(wpt->longitude);          /* longitude */
        FWRITE_DBL(wpt->altitude, unknown_alt); /* altitude */
        FWRITE_CSTR(wpt->notes);
-       FWRITE_DBL(GMSD_GET(proximity, 0), 0);  /* proximity */
+       FWRITE_DBL(WAYPT_GET(wpt, proximity, 0), 0);    /* proximity */
        FWRITE_i32(display);                    /* display */
        FWRITE_i32(0);                          /* color (colour) */
        FWRITE_i32(icon);                       /* icon */
@@ -1195,7 +1195,7 @@ write_waypoint(
        }
                
        FWRITE_i16(GMSD_GET(category, gdb_category));
-       FWRITE_DBL(GMSD_GET(temperature, 0), 0);
+       FWRITE_DBL(WAYPT_GET(wpt, temperature, 0), 0);
        FWRITE_TIME(wpt->creation_time);
 
        /* VERSION DEPENDENT CODE */
index b59e2a4097feeaf3d18cf48ac159a82f0bca8ec1..8fb1cbcc3c759de5591223a151bff53a75cb9f54 100644 (file)
--- a/gpilots.c
+++ b/gpilots.c
@@ -277,7 +277,7 @@ data_read(void)
                          fi.i = le_read32(&rec->wpt.d108.dpth);
                          wpt_tmp->depth = fi.f;
                          fi.i = le_read32(&rec->wpt.d108.dist);
-                         wpt_tmp->proximity = fi.f;
+                         WAYPT_SET(wpt_tmp, proximity, fi.f);
                          wpt_tmp->wpt_flags.icon_descr_is_dynamic = 0;
                          wpt_tmp->icon_descr = gt_find_desc_from_icon_number((rec->wpt.d108.smbl[1] << 8) + rec->wpt.d108.smbl[0], PCX, NULL);
                          waypt_add(wpt_tmp);
diff --git a/kml.c b/kml.c
index 38564903b1748c3a148d78af5aab6c0cd0e0919d..47ad9937eb088df874104922e501d15bb3eb8569 100644 (file)
--- a/kml.c
+++ b/kml.c
@@ -537,7 +537,7 @@ static void kml_output_description(const waypoint *pt)
        if (pt->altitude != unknown_alt) TD2("Altitude: %.1f %s", alt, alt_units);
        if (pt->heartrate) TD("Heart rate: %d", pt->heartrate);
        if (pt->cadence) TD("Cadence: %d", pt->cadence);
-       if (pt->temperature) TD("Temperature: %.1f", pt->temperature);
+       if (pt->wpt_flags.temperature) TD("Temperature: %.1f", pt->temperature);
        if (pt->speed > 0) {
                char *spd_units;
                double spd = fmt_speed(pt->speed, &spd_units);
index edc5afd69b469c23d59c4e235410a3733c602e10..3825e7ab48aa6fd9c98444cdc8573eb7a31ef401 100644 (file)
@@ -582,7 +582,7 @@ mps_waypoint_r(FILE *mps_file, int mps_ver, waypoint **wpt, unsigned int *mpscla
        thisWaypoint->latitude = GPS_Math_Semi_To_Deg(lat);
        thisWaypoint->longitude = GPS_Math_Semi_To_Deg(lon);
        thisWaypoint->altitude = mps_altitude;
-       thisWaypoint->proximity = mps_proximity;
+       if (mps_proximity != unknown_alt) WAYPT_SET(thisWaypoint, proximity, mps_proximity);
        thisWaypoint->depth = mps_depth;
 
        /* might need to change this to handle version dependent icon handling */
@@ -616,7 +616,7 @@ mps_waypoint_w(FILE *mps_file, int mps_ver, const waypoint *wpt, const int isRou
        int colour = 0;                 /*  (unknown colour) black is 1, white is 16 */
 
        double  mps_altitude = wpt->altitude;
-       double  mps_proximity = (mpsuseprox ? wpt->proximity : unknown_alt);
+       double  mps_proximity = (mpsuseprox ? WAYPT_GET(wpt, proximity, unknown_alt) : unknown_alt);
        double  mps_depth = (mpsusedepth ? wpt->depth : unknown_alt);
        
        lat = GPS_Math_Deg_To_Semi(wpt->latitude);
diff --git a/ozi.c b/ozi.c
index b33ccd89a68c6b420f0557dfba30062daa90b124..104de1354991cf0dae859e8921d768d112d3a682 100644 (file)
--- a/ozi.c
+++ b/ozi.c
@@ -421,7 +421,7 @@ ozi_parse_waypt(int field, char *str, waypoint * wpt_tmp, ozi_fsdata *fsdata)
         break;
     case 13:
         /* proximity distance - meters */
-       wpt_tmp->proximity = atof(str);
+       WAYPT_SET(wpt_tmp, proximity, atof(str));
         break;
     case 14:
         /* altitude in feet */
@@ -731,7 +731,7 @@ ozi_waypt_pr(const waypoint * wpt)
             "%d,%s,%.6f,%.6f,%.5f,%d,%d,%d,%d,%d,%s,%d,%d,",
             index, shortname, wpt->latitude, wpt->longitude, ozi_time, 0,
             1, 3, fs->fgcolor, fs->bgcolor, description, 0, 0);
-    if (wpt->proximity > 0)
+    if (wpt->wpt_flags.proximity && (wpt->proximity > 0))
        gbfprintf(file_out, "%.1f,", wpt->proximity);
     else
        gbfprintf(file_out,"0,");
index c5240617041e57f1935b15076b05ce9a86a89778..8f0ded034fda177e762bacee7f76ba5fa1cb4bc4 100644 (file)
--- a/stmsdf.c
+++ b/stmsdf.c
@@ -273,7 +273,7 @@ parse_point(char *line)
                                        case 0: 
                                                wpt->speed = atof(str) * 3.6; break;
                                        case 3: 
-                                               wpt->proximity = atof(str); 
+                                               WAYPT_SET(wpt, proximity, atof(str));
                                                xasprintf(&wpt->notes, "Alarm point: radius=%s", str);
                                                break;
                                }
index edef30b1af181583f976b8ccb3b813e59ff7fca4..227f68b0365aee314b1e8813409e1b3158c33fe7 100644 (file)
--- a/unicsv.c
+++ b/unicsv.c
 #include "defs.h"
 #include "csv_util.h"
 #include "jeeps/gpsmath.h"
+#include "strptime.h"
+#include <string.h>
 
 #define MYNAME "unicsv"
 
-static gbfile *file_in;
+typedef enum {
+       fld_shortname = 0,
+       fld_latitude,
+       fld_longitude,
+       fld_description,
+       fld_notes,
+       fld_url,
+       fld_altitude,
+       fld_utm_zone,
+       fld_utm_char,
+       fld_utm_northing,
+       fld_utm_easting,
+       fld_utm,
+       fld_bng,
+       fld_bng_zone,
+       fld_bng_northing,
+       fld_bng_easting,
+       fld_hdop,
+       fld_pdop,
+       fld_vdop,
+       fld_sat,
+       fld_fix,
+       fld_utc_date,
+       fld_utc_time,
+       fld_course,
+       fld_speed,
+       fld_temperature,
+       fld_temperature_f,
+       fld_heartrate,
+       fld_cadence,
+       fld_proximity,
+       fld_depth,
+       fld_terminator
+} field_e;
+
+#define STR_LEFT       1
+#define STR_RIGHT      2
+#define STR_ANY                4
+#define STR_EQUAL      8
+#define STR_CASE       16
+
+typedef struct {
+       char *name;
+       field_e type;
+       gbuint32 options;
+       
+} field_t;
 
-/* This structure must contain only ints.  Firstval must be first.
- * This is block initialized.
+/*
+ * ! Use always underscores in field names !
+ * we check a second time after replacing underscores with spaces
  */
-struct {
-       int firstval;
-       int latcol;
-       int loncol;
-       int namecol;
-       int desccol;
-       int notescol;
-       int altcol;
-       int urlcol;
-       int utmzcol; /* Zone */
-       int utmncol; /* Northing */
-       int utmecol; /* Easting */
-       int utmccol; /* Zone character */
-} unicsv_fieldpos;
+static field_t fields_def[] = {
+       { "name",       fld_shortname, STR_ANY },
+       { "descr",      fld_description, STR_ANY },
+       { "notes",      fld_notes, STR_ANY },
+       { "comment",    fld_notes, STR_ANY },
+       { "text",       fld_notes, STR_ANY },
+       { "url",        fld_url, STR_ANY },
+       { "lat",        fld_latitude, STR_ANY },
+       { "lon",        fld_longitude, STR_ANY },
+       { "alt",        fld_altitude, STR_ANY },
+       { "ele",        fld_altitude, STR_ANY },
+       { "utc_z",      fld_utm_zone, STR_ANY },
+       { "utm_c",      fld_utm_char, STR_ANY },
+       { "utm_n",      fld_utm_northing, STR_ANY },
+       { "utm_n",      fld_utm_easting, STR_ANY },
+       { "utm",        fld_utm, STR_EQUAL },
+       { "bng_z",      fld_bng_zone, STR_ANY },
+       { "bng_n",      fld_bng_northing, STR_ANY },
+       { "bng_n",      fld_bng_easting, STR_ANY },
+       { "bng",        fld_bng, STR_EQUAL },
+       { "hdop",       fld_hdop, STR_ANY },
+       { "pdop",       fld_pdop, STR_ANY },
+       { "vdop",       fld_vdop, STR_ANY },
+       { "sat",        fld_sat, STR_ANY },
+       { "fix",        fld_fix, STR_ANY },
+       { "utc_d",      fld_utc_date, STR_ANY },
+       { "utc_t",      fld_utc_time, STR_ANY },
+       { "head",       fld_course, STR_ANY },
+       { "course",     fld_course, STR_ANY },
+       { "speed",      fld_speed, STR_ANY },
+       { "tempf",      fld_temperature_f, STR_EQUAL }, /* degrees fahrenheit */
+       { "temp",       fld_temperature, STR_ANY },     /* degrees celsius by default */
+       { "heart",      fld_heartrate, STR_ANY },
+       { "cadence",    fld_cadence, STR_ANY },
+       { "prox",       fld_proximity, STR_ANY },
+       { "depth",      fld_depth, STR_ANY },
+       { NULL,         fld_terminator, 0 }
+};
 
+static field_e *unicsv_fields_tab;
+static int unicsv_fields_tab_ct;
 static double unicsv_altscale;
 static char *unicsv_fieldsep;
+static gbfile *file_in;
+static gpsdata_type unicsv_data_type;
+static route_head *unicsv_track;
+
+static arglist_t unicsv_args[] = { ARG_TERMINATOR };
 
-static
-arglist_t unicsv_args[] = {
-       ARG_TERMINATOR
-};
 
 /* helpers */
 
 // #define UNICSV_IS(f) (0 == strcmp(s, f))
 #define UNICSV_CONTAINS(f) (0 != strstr(s, f))
 
+static char
+unicsv_compare_fields(char *s, const field_t *f)
+{
+       char *name = (char *)f->name;
+       char *test = s;
+       char result;
+
+       if (! (f->options & STR_CASE)) {
+               test = strupper(xstrdup(s));
+               name = strupper(xstrdup(f->name));
+       }
+
+       if (f->options & STR_EQUAL) {
+               result = (strcmp(test, name) == 0);
+       }
+       else if (f->options & STR_ANY) {
+               result = (strstr(test, name) != NULL);
+       }
+       else {
+               int len = strlen(name);
+               
+               if (f->options & STR_LEFT) {
+                       result = (strncmp(test, name, len) == 0);
+               }
+/*
+               else if (f->options & STR_RIGHT) {
+                       result = (strrncmp(test, name, len) == 0);
+               }
+*/
+               else {
+                       result = 0;     /* what should we do here ? */
+               }
+       }
+
+       if ((! result) && (strchr(test, ' ') != NULL)) {
+               char *tmp = gstrsub(test, " ", "_");
+               result = unicsv_compare_fields(tmp, f);
+               xfree(tmp);
+       }
+       
+       if (name != f->name) {
+               xfree(name);
+               xfree(test);
+       }
+
+       return result;
+}
+
+
 static void
 unicsv_fondle_header(char *ibuf)
 {
        char *s;
-       unsigned int i;
-       int *ip = &unicsv_fieldpos.firstval;
-
-       for (i = 0; i < sizeof(unicsv_fieldpos) / sizeof(int); i++, ip++) {
-               *ip = -1;
-       }
+       int i, column;
 
        /* Convert the entire header to lower case for convenience. 
         * If we see a tab in that header, we decree it to be tabsep.
@@ -84,45 +204,38 @@ unicsv_fondle_header(char *ibuf)
                }
        }
 
-       s = csv_lineparse(ibuf, unicsv_fieldsep, "", 0);
-       for (i=0; s; i++,s = csv_lineparse(NULL, unicsv_fieldsep, "", 0)) {
-               if (UNICSV_CONTAINS("lat")) {
-                       unicsv_fieldpos.latcol = i;
-               }
-               else if (UNICSV_CONTAINS("lon")) {
-                       unicsv_fieldpos.loncol = i;
-               }
-               else if (UNICSV_CONTAINS("desc")) {
-                       unicsv_fieldpos.desccol = i;
-               }
-               else if (UNICSV_CONTAINS("name")) {
-                       unicsv_fieldpos.namecol = i;
+       column = -1;
+       while ((s = csv_lineparse(ibuf, unicsv_fieldsep, "", 0))) {
+               
+               field_t *f = &fields_def[0];
+               
+               ibuf = NULL;
+               column++;
+               unicsv_fields_tab_ct++;
+               s = lrtrim(s);
+               
+               if (column % 4 == 0) {
+                       int sz = (column + 4) * sizeof(*unicsv_fields_tab);
+                       if (column == 0) unicsv_fields_tab = xmalloc(sz);
+                       else unicsv_fields_tab = xrealloc(unicsv_fields_tab, sz);
+                       for (i = 0; i < 4; i++) unicsv_fields_tab[column + i] = fld_terminator;
                }
-               else if (UNICSV_CONTAINS("notes")) {
-                       unicsv_fieldpos.notescol = i;
+
+               while (f->name) {
+                       if (unicsv_compare_fields(s, f)) {
+                               unicsv_fields_tab[column] = f->type;
+                               break;
+                       }
+                       f++;
                }
-               else if (UNICSV_CONTAINS("alt")) {
-                       unicsv_fieldpos.altcol = i;
+               
+               /* handle some special items */
+               if (f->type == fld_altitude) {
                        if (UNICSV_CONTAINS("ft") || UNICSV_CONTAINS("feet")) {
                                unicsv_altscale = FEET_TO_METERS(1);
                        }
                }
-               else if (UNICSV_CONTAINS("url")) {
-                       unicsv_fieldpos.urlcol = i;
-               }
-               else if (UNICSV_CONTAINS("utm z")) {
-                       unicsv_fieldpos.utmzcol = i;
-               }
-               else if (UNICSV_CONTAINS("utm n")) {
-                       unicsv_fieldpos.utmncol = i;
-               }
-               else if (UNICSV_CONTAINS("utm e")) {
-                       unicsv_fieldpos.utmecol = i;
-               }
-               else if (UNICSV_CONTAINS("utm c")) {
-                       unicsv_fieldpos.utmccol = i;
-               }
-/* todo: speed, course, hdop, sat, date, time, maybe a few others */
+/* todo: date, time, maybe a few others */
        }
 }
 
@@ -131,6 +244,11 @@ unicsv_rd_init(const char *fname)
 {
        char *c;
        unicsv_altscale = 1.0;
+       
+       unicsv_fields_tab = NULL;
+       unicsv_fields_tab_ct = 0;
+       unicsv_data_type = wptdata;
+       unicsv_track = NULL;
 
        file_in = gbfopen(fname, "rb", MYNAME);
 
@@ -144,65 +262,236 @@ static void
 unicsv_rd_deinit(void)
 {
        gbfclose(file_in);
+       if (unicsv_fields_tab) xfree(unicsv_fields_tab);
 }
 
 static void
 unicsv_parse_one_line(char *ibuf)
 {
        char *s;
-       waypoint *wpt;
-       int i;
+       waypoint *wpt = NULL;
+       int column;
        int  utmz = -9999;
        double utme = 0;
        double utmn = 0;
        char utmc = 'N';
+       char bng_zone[3] = "";
+       double bng_easting = 0;
+       double bng_northing = 0;
+       struct tm tm;
+       char *ok;
+       int checked = 0;
 
-       s = csv_lineparse(ibuf, unicsv_fieldsep, "\"", 0);
-       if (s == NULL) return;
-       
        wpt = waypt_new();
+       column = -1;
+       while ((s = csv_lineparse(ibuf, unicsv_fieldsep, "\"", 0))) {
+       
+               if (column > unicsv_fields_tab_ct) break;       /* extra fields on line */
 
-       for (i=0; s; i++, s = csv_lineparse(NULL, unicsv_fieldsep, "\"", 0)) {
+               ibuf = NULL;
+               column++;
+               checked++;
                s = lrtrim(s);
-               if (i == unicsv_fieldpos.latcol) {
+
+               switch(unicsv_fields_tab[column]) {
+               
+               case fld_latitude:
                        human_to_dec( s, &wpt->latitude, &wpt->longitude, 1 );
-               }
-               else if (i == unicsv_fieldpos.loncol) {
+                       break;
+                       
+               case fld_longitude:
                        human_to_dec( s, &wpt->latitude, &wpt->longitude, 2 );
-               }
-               else if (i == unicsv_fieldpos.namecol) {
-                       wpt->shortname = xstrdup(s);
-               }
-               else if (i == unicsv_fieldpos.desccol) {
-                       wpt->description = xstrdup(s);
-               }
-               else if (i == unicsv_fieldpos.notescol) {
-                       wpt->notes = xstrdup(s);
-               }
-               else if (i == unicsv_fieldpos.urlcol) {
-                       wpt->url = xstrdup(s);
-               }
-               else if (i == unicsv_fieldpos.altcol) {
+                       break;
+                       
+               case fld_shortname:
+                       if (*s) wpt->shortname = xstrdup(s);
+                       break;
+                       
+               case fld_description:
+                       if (*s) wpt->description = xstrdup(s);
+                       break;
+
+               case fld_notes:
+                       if (*s) wpt->notes = xstrdup(s);
+                       break;
+
+               case fld_url:
+                       if (*s) wpt->url = xstrdup(s);
+                       break;
+
+               case fld_altitude:
                        wpt->altitude = atof(s) * unicsv_altscale;
-               }
-               else if (i == unicsv_fieldpos.utmzcol) {
+                       break;
+
+               case fld_utm_zone:
                        utmz = atoi(s);
-               }
-               else if (i == unicsv_fieldpos.utmecol) {
+                       break;
+                       
+               case fld_utm_easting:
                        utme = atof(s);
-               }
-               else if (i == unicsv_fieldpos.utmncol) {
+                       break;
+                       
+               case fld_utm_northing:
                        utmn = atof(s);
-               }
-               else if (i == unicsv_fieldpos.utmccol) {
+                       break;
+                       
+               case fld_utm_char:
                        utmc = toupper(s[0]);
+                       break;
+                       
+               case fld_utm:
+                       parse_coordinates(s, DATUM_WGS84, grid_utm,
+                               &wpt->latitude, &wpt->longitude, MYNAME);
+                       break;
+
+               case fld_bng:
+                       parse_coordinates(s, DATUM_OSGB36, grid_bng,
+                               &wpt->latitude, &wpt->longitude, MYNAME);
+                       break;
+                       
+               case fld_bng_zone:
+                       strncpy(bng_zone, s, sizeof(bng_zone));
+                       strupper(bng_zone);
+                       break;
+
+               case fld_bng_northing:
+                       bng_northing = atof(s);
+                       break;
+
+               case fld_bng_easting:
+                       bng_easting = atof(s);
+                       break;
+                       
+               case fld_hdop:
+                       wpt->hdop = atof(s);
+                       unicsv_data_type = trkdata;
+                       break;
+
+               case fld_pdop:
+                       wpt->pdop = atof(s);
+                       unicsv_data_type = trkdata;
+                       break;
+
+               case fld_vdop:
+                       wpt->vdop = atof(s);
+                       unicsv_data_type = trkdata;
+                       break;
+
+               case fld_sat:
+                       wpt->sat = atoi(s);
+                       unicsv_data_type = trkdata;
+                       break;
+
+               case fld_fix:
+                       unicsv_data_type = trkdata;
+                       if (case_ignore_strcmp(s, "none") == 0)
+                               wpt->fix = fix_none;
+                       else if (case_ignore_strcmp(s, "2d") == 0)
+                               wpt->fix = fix_2d;
+                       else if (case_ignore_strcmp(s, "3d") == 0)
+                               wpt->fix = fix_3d;
+                       else if (case_ignore_strcmp(s, "dgps") == 0)
+                               wpt->fix = fix_dgps;
+                       else if (case_ignore_strcmp(s, "pps") == 0)
+                               wpt->fix = fix_pps;
+                       else wpt->fix = fix_unknown;
+                       break;
+
+               case fld_utc_date:
+                       memset(&tm, 0, sizeof(tm));
+                       if (strchr(s, '.'))
+                               ok = strptime(s, "%d.%m.%Y", &tm);
+                       else
+                               ok = strptime(s, "%d/%m/%Y", &tm);
+                       if (ok) {
+                               tm.tm_isdst = -1;
+                               wpt->creation_time += mkgmtime(&tm);
+                       }
+                       else
+                               fatal(MYNAME ": Could not convert date string (%s).\n", s);
+                       break;
+                       
+               case fld_utc_time:
+                       memset(&tm, 0, sizeof(tm));
+                       if (strptime( s, "%H:%M:%S", &tm)) {
+                               wpt->creation_time += (
+                                       (SECONDS_PER_HOUR * tm.tm_hour) +
+                                       (60L * tm.tm_min) + tm.tm_sec
+                               );
+                       }
+                       break;
+
+               case fld_speed:
+                       wpt->speed = atof(s);
+                       unicsv_data_type = trkdata;
+                       break;
+
+               case fld_course:
+                       wpt->course = atof(s);
+                       unicsv_data_type = trkdata;
+                       break;
+                       
+               case fld_temperature:
+                       WAYPT_SET(wpt, temperature, atof(s));
+                       break;
+
+               case fld_temperature_f:
+                       WAYPT_SET(wpt, temperature, FAHRENHEIT_TO_CELSIUS(atof(s)));
+                       break;
+
+               case fld_heartrate:
+                       wpt->heartrate = atoi(s);
+                       unicsv_data_type = trkdata;
+                       break;
+
+               case fld_cadence:
+                       wpt->cadence = atoi(s);
+                       unicsv_data_type = trkdata;
+                       break;
+
+               case fld_proximity:
+                       WAYPT_SET(wpt, proximity, atof(s));
+                       break;
+
+               case fld_depth:
+                       wpt->depth = atof(s);
+                       break;
+                       
+               case fld_terminator: /* dummy */
+                       checked--;
+                       break;
                }
        }
-       if (utmz  != -9999) {
-               GPS_Math_UTM_EN_To_WGS84(&wpt->latitude, &wpt->longitude,
-                       utme, utmn, utmz, utmc);
+
+       if (checked == 0) {
+               waypt_free(wpt);
+               return;
+       }
+       
+       if (utmz != -9999) {
+               GPS_Math_UTM_EN_To_Known_Datum(&wpt->latitude, &wpt->longitude,
+                       utme, utmn, utmz, utmc, DATUM_WGS84);
+       }
+
+       if (bng_zone[0]) {
+               if (! GPS_Math_UKOSMap_To_WGS84_M(
+                               bng_zone, bng_easting, bng_northing,
+                               &wpt->latitude, &wpt->longitude))
+                       fatal(MYNAME ": Unable to convert BNG coordinates (%s %.f %.f)!\n",
+                               bng_zone, bng_easting, bng_northing);
+       }
+
+       switch(unicsv_data_type) {
+               case trkdata:
+                       if (! unicsv_track) {
+                               unicsv_track = route_head_alloc();
+                               track_add_head(unicsv_track);
+                       }
+                       track_add_wpt(unicsv_track, wpt);
+                       break;
+               default:
+                       waypt_add(wpt);
        }
-       waypt_add(wpt);
 }
 
 static void